package com.retry.task.core.task;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.retry.task.core.constants.HeartResultEnum;
import com.retry.task.core.constants.RetryTaskURIEnum;
import com.retry.task.core.heart.HeartTickDO;
import com.retry.task.core.heart.ServerHeartHolder;
import com.retry.task.core.model.AttributeModel;
import com.retry.task.core.model.RetryTaskDTO;
import com.retry.task.core.model.base.Result;
import com.retry.task.core.threadlocal.RetryTaskThreadLocal;
import com.retry.task.core.utils.CommonExecuteUtils;
import com.retry.task.core.utils.HttpClientUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

/**
 * @author gao.gwq
 * @version 1.0
 * @date 2022/5/1  17:14
 * @Description TODO
 */
public class RetryTaskFactory {

    private RetryTaskFactory() {

    }

    public static RetryTaskFactory getInstance() {
        return InnerClass.RETRY_TASK_SERVICE;
    }

    private static final class InnerClass {
        private static final RetryTaskFactory RETRY_TASK_SERVICE = new RetryTaskFactory();
    }

    public Result<Long> createRetryTask(RetryTaskDTO retryTaskDTO) {

        if (retryTaskDTO == null) {
            return Result.getFail("100", "retryTaskDTO is null");
        }
        if (retryTaskDTO.getToken() == null) {
            return Result.getFail("100", "token is null or empty");
        }
        if (StringUtils.isEmpty(retryTaskDTO.getTaskName())) {
            return Result.getFail("100", "taskName is null or empty");
        }
        if (StringUtils.isEmpty(retryTaskDTO.getProjectName())) {
            return Result.getFail("100", "projectName is null or empty");
        }
        Result<HeartTickDO> heartTickResult = getHeartTickDO();
        if (!heartTickResult.isSuccess()) {
            return Result.getFail(heartTickResult.getCode(), heartTickResult.getErrMsg());
        }
        String realUri = heartTickResult.getData().getServerIp() + RetryTaskURIEnum.CREATE_RETRY_TASK.getUri();
        setAttributeModel(retryTaskDTO);
        Result createTaskReslut = HttpClientUtils.postBody(realUri, retryTaskDTO,
                Long.class);
        if (!createTaskReslut.isSuccess()) {
            return Result.getFail(createTaskReslut.getCode(), createTaskReslut.getErrMsg());
        }
        return createTaskReslut;
    }

    /**
     * 设置默认的参数
     *
     * @param retryTaskDTO
     */
    private void setAttributeModel(RetryTaskDTO retryTaskDTO) {
        AttributeModel attributeModel = RetryTaskThreadLocal.getAttributeModel();

        if (attributeModel == null) {
            attributeModel = new AttributeModel();
            attributeModel.setProjectName(retryTaskDTO.getProjectName());
            attributeModel.setTaskName(retryTaskDTO.getTaskName());
            attributeModel.setLoopNum(1);
            doSetAttribute(retryTaskDTO, attributeModel);
            return;
        }

        String originKey = retryTaskDTO.getProjectName() + "_" + retryTaskDTO.getTaskName();
        String newKey = attributeModel.getProjectName() + "_" + attributeModel.getTaskName();
        if (!StringUtils.equals(originKey, newKey)) {
            attributeModel = new AttributeModel();
            attributeModel.setProjectName(retryTaskDTO.getProjectName());
            attributeModel.setTaskName(retryTaskDTO.getTaskName());
            attributeModel.setLoopNum(1);
        } else {
            attributeModel.setLoopNum(attributeModel.getLoopNum() + 1);
        }
        doSetAttribute(retryTaskDTO, attributeModel);
    }

    private static void doSetAttribute(RetryTaskDTO retryTaskDTO, AttributeModel attributeModel) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("attributeModel", attributeModel);
        CommonExecuteUtils.setFieldVal(paramMap, retryTaskDTO.getClass().getDeclaredFields(), retryTaskDTO);
    }


    public Result<HeartTickDO> getHeartTickDO() {
        List<HeartTickDO> heartTickDOList = ServerHeartHolder.getServerHeartList();
        if (CollectionUtils.isEmpty(heartTickDOList)) {
            return Result.getFail("100", "server list is empty");
        }
        HeartTickDO heartTickDO = getBestServer(heartTickDOList);
        //如果没有取到有效的服务，随机取一个
        if (heartTickDO == null) {
            heartTickDO = heartTickDOList.get(0);
        }
        return Result.getSuccess(heartTickDO);
    }

    /**
     * 取最近一次心跳成功的，切耗时最短的
     *
     * @return
     */
    private HeartTickDO getBestServer(List<HeartTickDO> heartTickDOList) {

        //取上次心跳成功的
        List<HeartTickDO> sucessList = heartTickDOList.stream().filter(
                        heartTickDO -> heartTickDO.getResult().equals(HeartResultEnum.SUCESS.getCode()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sucessList)) {
            return null;
        }
        Comparator<HeartTickDO> costTimeCoparator = (o1, o2) -> {
            if (o1.getTimeCost() > o1.getTimeCost()) {
                return 1;
            }
            return -1;
        };
        Comparator<HeartTickDO> heartTimeComparator = (o1, o2) -> o2.getLastHeartTime().compareTo(
                o1.getLastHeartTime());
        sucessList.sort(heartTimeComparator.thenComparing(costTimeCoparator));
        return sucessList.get(0);
    }
}
